home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / pager.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  49KB  |  2,148 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. #include "mutt.h"
  20. #include "mutt_curses.h"
  21. #include "mutt_regex.h"
  22. #include "keymap.h"
  23. #include "mutt_menu.h"
  24. #include "sort.h"
  25. #ifdef _PGPPATH
  26. #include "pgp.h"
  27. #endif
  28.  
  29. #include <sys/stat.h>
  30. #include <ctype.h>
  31. #include <unistd.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34.  
  35. #define M_NOSHOW    0
  36. #define M_SHOWFLAT    (1 << 0)
  37. #define M_SHOWCOLOR    (1 << 1)
  38. #define M_HIDE        (1 << 2)
  39. #define M_SEARCH    (1 << 3)
  40. #define M_TYPES        (1 << 4)
  41. #define M_SHOW        (M_SHOWCOLOR | M_SHOWFLAT)
  42.  
  43. #define ISHEADER(x) ((x) == MT_COLOR_HEADER || (x) == MT_COLOR_HDEFAULT)
  44.  
  45. #define CHECK_MODE    if (!hdr) \
  46.             { \
  47.                   mutt_flushinp (); \
  48.                 mutt_error ("Not available in this menu."); \
  49.                 break; \
  50.             }
  51.  
  52. #define CHECK_READONLY    if (Context->readonly) \
  53.             { \
  54.                 mutt_flushinp (); \
  55.                 mutt_error ("Mailbox is read-only.");    \
  56.                 break; \
  57.             }
  58.  
  59. struct q_class_t
  60. {
  61.   int length;
  62.   int color;
  63.   char *prefix;
  64.   struct q_class_t *next, *prev;
  65.   struct q_class_t *down, *up;
  66. };
  67.  
  68. struct syntax_t
  69. {
  70.   int color;
  71.   short first;
  72.   short last;
  73. };
  74.  
  75. struct line_t
  76. {
  77.   long offset;
  78.   short type;
  79.   short continuation;
  80.   short chunks;
  81.   short search_cnt;
  82.   struct syntax_t *syntax;
  83.   struct syntax_t *search;
  84.   struct q_class_t *quote;
  85. };
  86.  
  87. #define ANSI_OFF       (1<<0)
  88. #define ANSI_BLINK     (1<<1)
  89. #define ANSI_BOLD      (1<<2)
  90. #define ANSI_UNDERLINE (1<<3)
  91. #define ANSI_REVERSE   (1<<4)
  92. #define ANSI_COLOR     (1<<5)
  93.  
  94. typedef struct _ansi_attr {
  95.   int attr;
  96.   int fg;
  97.   int bg;
  98.   int pair;
  99. } ansi_attr;
  100.  
  101. static short InHelp = 0;
  102.  
  103. #define NumSigLines 4
  104.  
  105. static int check_sig (const char *s, struct line_t *info, int n)
  106. {
  107.   int count = 0;
  108.  
  109.   while (n > 0 && count <= NumSigLines)
  110.   {
  111.     if (info[n].type != MT_COLOR_SIGNATURE)
  112.       break;
  113.     count++;
  114.     n--;
  115.   }
  116.  
  117.   if (count == 0)
  118.     return (-1);
  119.  
  120.   if (count > NumSigLines)
  121.   {
  122.     /* check for a blank line */
  123.     while (*s)
  124.     {
  125.       if (!ISSPACE (*s))
  126.     return 0;
  127.       s++;
  128.     }
  129.  
  130.     return (-1);
  131.   }
  132.  
  133.   return (0);
  134. }
  135.  
  136. static void
  137. resolve_color (struct line_t *lineInfo, int n, int cnt, int flags, int special,
  138.     ansi_attr *a)
  139. {
  140.   int def_color;        /* color without syntax hilight */
  141.   int color;            /* final color */
  142.   static int last_color;    /* last color set */
  143.   int search = 0, i, m;
  144.  
  145.   if (!cnt)
  146.     last_color = -1;        /* force attrset() */
  147.  
  148.   if (lineInfo[n].continuation)
  149.   {
  150.     if (!cnt && option (OPTMARKERS))
  151.     {
  152.       SETCOLOR (MT_COLOR_MARKERS);
  153.       addch ('+');
  154.       last_color = ColorDefs[MT_COLOR_MARKERS];
  155.     }
  156.     m = (lineInfo[n].syntax)[0].first;
  157.     cnt += (lineInfo[n].syntax)[0].last;
  158.   }
  159.   else
  160.     m = n;
  161.   if (!(flags & M_SHOWCOLOR))
  162.     def_color = ColorDefs[MT_COLOR_NORMAL];
  163.   else if (lineInfo[m].type == MT_COLOR_HEADER)
  164.     def_color = (lineInfo[m].syntax)[0].color;
  165.   else
  166.     def_color = ColorDefs[lineInfo[m].type];
  167.  
  168.   if ((flags & M_SHOWCOLOR) && lineInfo[m].type == MT_COLOR_QUOTED)
  169.   {
  170.     struct q_class_t *class = lineInfo[m].quote;
  171.  
  172.     if (class)
  173.     {
  174.       def_color = class->color;
  175.  
  176.       while (class && class->length > cnt)
  177.       {
  178.     def_color = class->color;
  179.     class = class->up;
  180.       }
  181.     }
  182.   }
  183.  
  184.   color = def_color;
  185.   if (flags & M_SHOWCOLOR)
  186.   {
  187.     for (i = 0; i < lineInfo[m].chunks; i++)
  188.     {
  189.       /* we assume the chunks are sorted */
  190.       if (cnt > (lineInfo[m].syntax)[i].last)
  191.     continue;
  192.       if (cnt < (lineInfo[m].syntax)[i].first)
  193.     break;
  194.       if (cnt != (lineInfo[m].syntax)[i].last)
  195.       {
  196.     color = (lineInfo[m].syntax)[i].color;
  197.     break;
  198.       }
  199.       /* don't break here, as cnt might be 
  200.        * in the next chunk as well */
  201.     }
  202.   }
  203.  
  204.   if (flags & M_SEARCH)
  205.   {
  206.     for (i = 0; i < lineInfo[m].search_cnt; i++)
  207.     {
  208.       if (cnt > (lineInfo[m].search)[i].last)
  209.     continue;
  210.       if (cnt < (lineInfo[m].search)[i].first)
  211.     break;
  212.       if (cnt != (lineInfo[m].search)[i].last)
  213.       {
  214.     color = ColorDefs[MT_COLOR_SEARCH];
  215.     search = 1;
  216.     break;
  217.       }
  218.     }
  219.   }
  220.  
  221.   /* handle "special" bold & underlined characters */
  222.   if (special || a->attr)
  223.   {
  224.     if (special == A_BOLD || (a->attr & ANSI_BOLD))
  225.     {
  226.       if (ColorDefs[MT_COLOR_BOLD] && !search)
  227.     color = ColorDefs[MT_COLOR_BOLD];
  228.       else
  229.     color ^= A_BOLD;
  230.     }
  231.     else if (special == A_UNDERLINE || (a->attr & ANSI_UNDERLINE))
  232.     {
  233.       if (ColorDefs[MT_COLOR_UNDERLINE] && !search)
  234.     color = ColorDefs[MT_COLOR_UNDERLINE];
  235.       else
  236.     color ^= A_UNDERLINE;
  237.     }
  238.     else if (a->attr & ANSI_REVERSE) 
  239.     {
  240.       color ^= A_REVERSE;
  241.     }
  242.     else if (a->attr & ANSI_BLINK) 
  243.     {
  244.       color ^= A_BLINK;
  245.     }
  246. #ifdef HAVE_COLOR
  247.     else if (a->attr & ANSI_COLOR)
  248.     {
  249.       if (a->pair == -1)
  250.     a->pair = mutt_alloc_color (a->fg,a->bg);
  251.       color = a->pair;
  252.     }
  253. #endif
  254.     else if (a->attr & ANSI_OFF)
  255.     {
  256.       a->attr = 0;
  257.     }
  258.   }
  259.  
  260.   if (color != last_color)
  261.   {
  262.     attrset (color);
  263.     last_color = color;
  264.   }
  265. }
  266.  
  267. static void
  268. append_line (struct line_t *lineInfo, int n, int cnt)
  269. {
  270.   int m;
  271.  
  272.   lineInfo[n+1].type = lineInfo[n].type;
  273.   (lineInfo[n+1].syntax)[0].color = (lineInfo[n].syntax)[0].color;
  274.   lineInfo[n+1].continuation = 1;
  275.  
  276.   /* find the real start of the line */
  277.   m = n;
  278.   while (m >= 0)
  279.   {
  280.     if (lineInfo[m].continuation == 0) break;
  281.     m--;
  282.   }
  283.   (lineInfo[n+1].syntax)[0].first = m;
  284.   (lineInfo[n+1].syntax)[0].last = (lineInfo[n].continuation) ? 
  285.     cnt + (lineInfo[n].syntax)[0].last : cnt;
  286. }
  287.  
  288. static void
  289. cleanup_quote (struct q_class_t **QuoteList)
  290. {
  291.   struct q_class_t *ptr;
  292.  
  293.   while (*QuoteList)
  294.   {
  295.     if ((*QuoteList)->down)
  296.       cleanup_quote (&((*QuoteList)->down));
  297.     ptr = (*QuoteList)->next;
  298.     safe_free ((void **) &(*QuoteList)->prefix);
  299.     safe_free ((void **) QuoteList);
  300.     *QuoteList = ptr;
  301.   }
  302.  
  303.   return;
  304. }
  305.  
  306. static struct q_class_t *
  307. classify_quote (struct q_class_t **QuoteList, const char *qptr,
  308.         int length, int *force_redraw, int *q_level)
  309. {
  310.   struct q_class_t *q_list = *QuoteList;
  311.   struct q_class_t *class = NULL, *tmp = NULL, *ptr;
  312.   char *tail_qptr;
  313.   int offset, tail_lng;
  314.  
  315.   /* Did I mention how much I like emulating Lisp in C? */
  316.  
  317.   /* classify quoting prefix */
  318.   while (q_list)
  319.   {
  320.     if (length <= q_list->length)
  321.     {
  322.       if (strncmp (qptr, q_list->prefix, length) == 0)
  323.       {
  324.     /* same prefix: return the current class */
  325.     if (length == q_list->length)
  326.       return q_list;
  327.  
  328.     /* found shorter common prefix */
  329.     if (tmp == NULL)
  330.     {
  331.       /* add a node above q_list */
  332.       tmp = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t));
  333.       tmp->prefix = (char *) safe_calloc (1, length + 1);
  334.       strncpy (tmp->prefix, qptr, length);
  335.       tmp->length = length;
  336.       if (*q_level >= ColorQuoteUsed)
  337.         *q_level = 1;
  338.       else
  339.         (*q_level)++;
  340.       tmp->color = ColorQuote[(*q_level) - 1];
  341.  
  342.       /* replace q_list by tmp in the top level list */
  343.       if (q_list->next)
  344.       {
  345.         tmp->next = q_list->next;
  346.         q_list->next->prev = tmp;
  347.       }
  348.       if (q_list->prev)
  349.       {
  350.         tmp->prev = q_list->prev;
  351.         q_list->prev->next = tmp;
  352.       }
  353.  
  354.       /* make q_list a child of tmp */
  355.       tmp->down = q_list;
  356.       q_list->up = tmp;
  357.  
  358.       /* q_list has no siblings */
  359.       q_list->next = NULL;
  360.       q_list->prev = NULL;
  361.  
  362.       /* update the root if necessary */
  363.       if (q_list == *QuoteList)
  364.         *QuoteList = tmp;
  365.  
  366.       /* tmp should be the return class too */
  367.       class = tmp;
  368.  
  369.       /* next class to test */
  370.       q_list = tmp->next;
  371.     }
  372.     else
  373.     {
  374.       /* save the next sibling for later */
  375.       ptr = q_list->next;
  376.  
  377.       /* unlink q_list from the top level list */
  378.       if (q_list->next)
  379.